home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / cctools / as / as.c < prev    next >
C/C++ Source or Header  |  1994-06-03  |  14KB  |  517 lines

  1. /* as.c - GAS main program.
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Main program for AS; a 32-bit assembler of GNU.
  22.  * Understands command arguments.
  23.  * Has a few routines that don't fit in other modules because they
  24.  * are shared.
  25.  *
  26.  *
  27.  *            bugs
  28.  *
  29.  * : initialisers
  30.  *    Since no-one else says they will support them in future: I
  31.  * don't support them now.
  32.  *
  33.  */
  34.  
  35. #include <signal.h>
  36. #include <string.h>
  37.  
  38. #include "as.h"
  39. #include "input-scrub.h"
  40. #include "symbols.h"
  41. #include "sections.h"
  42. #include "read.h"
  43. #include "md.h"
  44. #include "messages.h"
  45. #include "xmalloc.h"
  46. #include "layout.h"
  47. #include "write_object.h"
  48.  
  49. /* ['x'] TRUE if "-x" seen. */
  50. char flagseen[128] = { 0 };
  51.  
  52. /* TRUE if -force_cpusubtype_ALL is specified */
  53. int force_cpusubtype_ALL = 0;
  54.  
  55. /* set to the corresponding cpusubtype if -arch flag is specified */
  56. cpu_subtype_t archflag_cpusubtype = -1;
  57.  
  58. /*
  59.  * .include "file" looks in source file dir, then stack.
  60.  * -I directories are added to the end, then the defaults are added.
  61.  */
  62. struct directory_stack include_defaults[] = {
  63.     { 0, "/NextDeveloper/Headers/" },
  64.     { 0, "/LocalDeveloper/Headers/" },
  65.     { 0, NULL }
  66. };
  67. struct directory_stack *include = NULL;    /* First dir to search */
  68. static struct directory_stack *include_tail = NULL;    /* Last in chain */
  69.  
  70. /* next_version is in next_version.c which is created by the Makefile */
  71. extern char next_version[];
  72. /* this is only used here, thus defined here (was in version.c in GAS) */
  73. static char version_string[] = "GNU assembler version 1.38\n";
  74.  
  75. /*
  76.  * The list of signals to catch if not ignored.
  77.  */
  78. static int sig[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0};
  79. static void got_sig(
  80.     int sig);
  81.  
  82. static void perform_an_assembly_pass(
  83.     int argc,
  84.     char **argv);
  85.  
  86. void
  87. main(
  88. int argc,
  89. char **argv,
  90. char **envp)
  91. {
  92.     char *progname;    /* argv[0] */
  93.     int    work_argc;    /* variable copy of argc */
  94.     char **work_argv;    /* variable copy of argv */
  95.     char *arg;        /* an arg to program */
  96.     char a;        /* an arg flag (after -) */
  97.     char *out_file_name;/* name of object file, argument to -o if specified */
  98.     int i;
  99.     char *specific_archflag;
  100.     struct directory_stack *dirtmp;
  101.  
  102.     progname = argv[0];
  103.  
  104.     /*
  105.      * Set up to catch the signals listed in sig[] that are not ignored.
  106.      */
  107.     for(i = 0; sig[i] != 0; i++)
  108.         if(signal(sig[i], SIG_IGN) != SIG_IGN)
  109.         signal(sig[i], got_sig);
  110.     /*
  111.      * Set the default for the flags that will be parsed.
  112.      */
  113.     memset(flagseen, '\0', sizeof(flagseen)); /* aint seen nothing yet */
  114.     specific_archflag = NULL;
  115.     out_file_name = "a.out";    /* default .o file */
  116.  
  117.     /*
  118.      * Call the initialization routines.
  119.      */
  120.     check_for_ProjectBuilder();    /* messages.c */
  121.     symbol_begin();            /* symbols.c */
  122.     sections_begin();        /* sections.c */
  123.     read_begin();            /* read.c */
  124.     md_begin();            /* MACHINE.c */
  125.     input_scrub_begin();        /* input_scrub.c */
  126.  
  127.     /*
  128.      * Parse arguments, but we are only interested in flags.
  129.      * When we find a flag, we process it then make it's argv[] NULL.
  130.      * This helps any future argv[] scanners avoid what we processed.
  131.      * Since it is easy to do here we interpret the special arg "-"
  132.      * to mean "use stdin" and we set that argv[] pointing to "".
  133.      * After we have munged argv[], the only things left are source file
  134.      * name(s) and ""(s) denoting stdin. These file names are used
  135.      * (perhaps more than once) later.
  136.      */
  137.     work_argc = argc - 1;        /* don't count argv[0] */
  138.     work_argv = argv + 1;        /* skip argv[0] */
  139.     for( ; work_argc-- ; work_argv++){
  140.  
  141.         /* work_argv points to this argument */
  142.         arg = *work_argv;
  143.  
  144.         /* Filename. We need it later. */
  145.         if(*arg != '-')
  146.         continue;
  147.  
  148.         /* Keep scanning args looking for flags. */
  149.         if (arg[1] == '-' && arg[2] == 0) {
  150.         /* "--" as an argument means read STDIN */
  151.         /* on this scan, we don't want to think about filenames */
  152.         *work_argv = "";    /* Code that means 'use stdin'. */
  153.         continue;
  154.         }
  155.  
  156.         /* This better be a switch ( -l where l is a letter. */
  157.         arg++;        /* -> letter. */
  158.  
  159.         /* scan all the 1-char flags */
  160.         while((a = *arg)){
  161.         arg ++;    /* arg -> after letter. */
  162.         a &= 0x7F;    /* ascii only please */
  163.         if(flagseen[(int)a] && (a != 'I') && (a != 'a') && (a != 'f'))
  164.             as_warn("%s: Flag option -%c has already been seen!",
  165.                 progname, a);
  166.         if(a != 'f')
  167.             flagseen[(int)a] = TRUE;
  168.         switch(a){
  169.         case 'f':
  170.             if(strcmp(arg-1, "force_cpusubtype_ALL") == 0){
  171.             force_cpusubtype_ALL = 1;
  172.             arg = "";    /* Finished with this arg. */
  173.             break;
  174.             }
  175.             /* -f means fast - no need for "app" preprocessor. */
  176.             flagseen[(int)a] = TRUE;
  177.             break;
  178.  
  179.         case 'L': /* -L means keep L* symbols */
  180.             break;
  181.  
  182.         case 'o':
  183.             if(*arg != '\0') /* Rest of argument is object file-name. */
  184.             out_file_name = arg;
  185.             else if(work_argc){    /* Want next arg for a file-name. */
  186.             *work_argv = NULL; /* This is not a file-name. */
  187.             work_argc--;
  188.             out_file_name = *++work_argv;
  189.             }
  190.             else
  191.             as_warn("%s: I expected a filename after -o. \"%s\" "
  192.                 "assumed.", progname, out_file_name);
  193.             arg = "";    /* Finished with this arg. */
  194.             break;
  195.  
  196.         case 'R':
  197.             /* -R means put data into text segment */
  198.             as_warn("%s: -R option not supported (use the "
  199.                 ".const directive)", progname);
  200.             flagseen['R'] = FALSE;
  201.             break;
  202.  
  203.         case 'v':
  204.             fprintf(stderr,"NeXT Computer, Inc. version "
  205.                 "%s, ", next_version);
  206.             fprintf(stderr, version_string);
  207.             if(*arg && strcmp(arg,"ersion"))
  208.             as_warn("Unknown -v option ignored");
  209.             while(*arg)
  210.             arg++;    /* Skip the rest */
  211.             break;
  212.  
  213.         case 'W':
  214.             /* -W means don't warn about things */
  215.             break;
  216.  
  217.         case 'I':
  218.             /* Add directory to path for includes */
  219.             dirtmp = (struct directory_stack *)
  220.             xmalloc(sizeof(struct directory_stack));
  221.             /* New one goes on the end */
  222.             dirtmp->next = 0;
  223.             if(include == 0)
  224.             include = dirtmp;
  225.             else
  226.             include_tail->next = dirtmp;
  227.             /* Tail follows the last one */
  228.             include_tail = dirtmp;
  229.             /* Rest of argument is include file-name. */
  230.             if(*arg)
  231.             dirtmp->fname = arg;
  232.             else if (work_argc){
  233.             /* Want next arg for a file-name. */
  234.             /* This is not a file-name. */
  235.             *work_argv = NULL;
  236.             work_argc--;
  237.             dirtmp->fname = *++work_argv;
  238.             }
  239.             else
  240.             as_warn("I expected a filename after -I.");
  241.             arg = "";    /* Finished with this arg. */
  242.             break;
  243.  
  244.         case 'g':
  245.             /* generate stabs for debugging assembly code */
  246.             break;
  247.  
  248.         case 'n':
  249.             /* no default .text section */
  250.             break;
  251.  
  252.         case 'd':
  253.             if(strcmp(arg-1, "dynamic") == 0){
  254.             arg = "";    /* Finished with this arg. */
  255.             flagseen[(int)'k'] = TRUE;
  256.             break;
  257.             }
  258.             goto unknown_flag;
  259.  
  260.         case 's':
  261.             if(strcmp(arg-1, "static") == 0){
  262.             arg = "";    /* Finished with this arg. */
  263.             flagseen[(int)'k'] = FALSE;
  264.             break;
  265.             }
  266.             goto unknown_flag;
  267.  
  268.         case 'N':
  269.             if(strcmp(arg-1, "NEXTSTEP-deployment-target") == 0){
  270.             arg = "";    /* Finished with this arg. */
  271.             /* Want next arg for a <release_tag> */
  272.             if(work_argc){
  273.                 /* This, "-NEXTST..." is not a file-name. */
  274.                 *work_argv = NULL;
  275.                 work_argc--;
  276.                 work_argv++;
  277.                 if(strcmp(*work_argv, "3.3") == 0){
  278.                 flagseen[(int)'k'] = TRUE;
  279.                 }
  280.                 else if(strcmp(*work_argv, "3.2") == 0){
  281.                 flagseen[(int)'k'] = FALSE;
  282.                 }
  283.                 else{
  284.                 as_fatal("I expected '3.2' or '3.3' after "
  285.                     "-NEXTSTEP-deployment-target.");
  286.                 }
  287.             }
  288.             else
  289.                 as_fatal("I expected a <release_tag> "
  290.                      "after -NEXTSTEP-deployment-target.");
  291.             break;
  292.             }
  293.             goto unknown_flag;
  294.  
  295.         case 'k':
  296.             /* use new features incompatible with 3.2 */
  297.             break;
  298.  
  299.         case 'V':
  300.             /* as driver's -V, verbose, flag */
  301.             break;
  302.  
  303.         case 'a':
  304.             if(strcmp(arg-1, "arch_multiple") == 0){
  305.             arch_multiple = 1;
  306.             arg = "";    /* Finished with this arg. */
  307.             break;
  308.             }
  309.             else if(strcmp(arg-1, "arch") == 0){
  310.             arg = "";    /* Finished with this arg. */
  311.             /* Want next arg for a <arch_type> */
  312.             if(work_argc){
  313.                 /* This, "-arch" is not a file-name. */
  314.                 *work_argv = NULL;
  315.                 work_argc--;
  316.                 work_argv++;
  317. #ifdef M68K
  318.                 if(strcmp(*work_argv, "m68030") == 0){
  319.                 if(archflag_cpusubtype != -1 &&
  320.                    archflag_cpusubtype !=
  321.                     CPU_SUBTYPE_MC68030_ONLY)
  322.                     as_fatal("can't specify both "
  323.                     "-arch m68030 and -arch "
  324.                     "m68040");
  325.                 specific_archflag = *work_argv;
  326.                 archflag_cpusubtype =
  327.                     CPU_SUBTYPE_MC68030_ONLY;
  328.                 }
  329.                 else if(strcmp(*work_argv,
  330.                         "m68040") == 0){
  331.                 if(archflag_cpusubtype != -1 &&
  332.                    archflag_cpusubtype !=
  333.                     CPU_SUBTYPE_MC68040)
  334.                     as_fatal("can't specify both "
  335.                     "-arch m68030 and -arch "
  336.                     "m68040");
  337.                 specific_archflag = *work_argv;
  338.                 archflag_cpusubtype =
  339.                     CPU_SUBTYPE_MC68040;
  340.                 }
  341.                 else if(strcmp(*work_argv, "m68k") != 0)
  342.                 as_fatal("I expected 'm68k', "
  343.                     "'m68030' or 'm68040' after "
  344.                     "-arch for this assembler.");
  345. #endif
  346. #ifdef M88K
  347.                 if(strcmp(*work_argv, "m88k") != 0)
  348.                 as_fatal("I expected 'm88k' after "
  349.                        "-arch for this assembler.");
  350. #endif
  351. #ifdef I860
  352.                 if(strcmp(*work_argv, "i860") != 0)
  353.                 as_fatal("I expected 'i860' after "
  354.                        "-arch for this assembler.");
  355. #endif
  356. #ifdef I386
  357.                 if(strcmp(*work_argv, "i486") == 0){
  358.                 if(archflag_cpusubtype != -1 &&
  359.                    archflag_cpusubtype !=
  360.                     CPU_SUBTYPE_486)
  361.                     as_fatal("can't specify more "
  362.                        "than one -arch flag ");
  363.                 specific_archflag = *work_argv;
  364.                 archflag_cpusubtype =
  365.                     CPU_SUBTYPE_486;
  366.                 }
  367.                 else if(strcmp(*work_argv,
  368.                        "i486SX") == 0){
  369.                 if(archflag_cpusubtype != -1 &&
  370.                    archflag_cpusubtype !=
  371.                     CPU_SUBTYPE_486SX)
  372.                     as_fatal("can't specify more "
  373.                        "than one -arch flag ");
  374.                 specific_archflag = *work_argv;
  375.                 archflag_cpusubtype =
  376.                     CPU_SUBTYPE_486SX;
  377.                 }
  378.                 else if(strcmp(*work_argv, "i586") ==0){
  379.                 if(archflag_cpusubtype != -1 &&
  380.                    archflag_cpusubtype !=
  381.                     CPU_SUBTYPE_586)
  382.                     as_fatal("can't specify more "
  383.                        "than one -arch flag ");
  384.                 specific_archflag = *work_argv;
  385.                 archflag_cpusubtype =
  386.                     CPU_SUBTYPE_586;
  387.                 }
  388.                 else if(strcmp(*work_argv,
  389.                        "i586SX") == 0){
  390.                 if(archflag_cpusubtype != -1 &&
  391.                    archflag_cpusubtype !=
  392.                     CPU_SUBTYPE_586SX)
  393.                     as_fatal("can't specify more "
  394.                        "than one -arch flag ");
  395.                 specific_archflag = *work_argv;
  396.                 archflag_cpusubtype =
  397.                     CPU_SUBTYPE_586SX;
  398.                 }
  399.                 else if(strcmp(*work_argv, "i386") != 0)
  400.                 as_fatal("I expected 'i386', 'i486'"
  401.                    " 'i486SX', 'i586' or 'i586SX' "
  402.                    "after -arch for this "
  403.                    "assembler.");
  404. #endif
  405. #ifdef HPPA
  406.                 if(strcmp(*work_argv, "hppa") != 0)
  407.                 as_fatal("I expected 'hppa' after "
  408.                      "-arch for this assembler.");
  409. #endif
  410. #ifdef SPARC
  411.                 if(strcmp(*work_argv, "sparc") != 0)
  412.                 as_fatal("I expected 'sparc' after "
  413.                      "-arch for this assembler.");
  414. #endif
  415.             }
  416.             else
  417.                 as_fatal("I expected an <arch_type> "
  418.                      "after -arch.");
  419.             break;
  420.             }
  421.             /* fall through for non -arch flag */
  422.         default:
  423. unknown_flag:
  424.             --arg;
  425.             if(md_parse_option(&arg, &work_argc, &work_argv) == 0)
  426.             as_warn("%s: I don't understand '%c' flag!", progname,
  427.                 a);
  428.             if(arg && *arg)
  429.             arg++;
  430.             break;
  431.         }
  432.         }
  433.         /*
  434.          * We have just processed a "-..." arg, which was not a
  435.          * file-name. Smash it so the
  436.          * things that look for filenames won't ever see it.
  437.          *
  438.          * Whatever work_argv points to, it has already been used
  439.          * as part of a flag, so DON'T re-use it as a filename.
  440.          */
  441.         *work_argv = NULL; /* NULL means 'not a file-name' */
  442.     }
  443.     if(flagseen['g'] == TRUE && flagseen['n'] == TRUE)
  444.         as_fatal("-g can't be specified if -n is specified");
  445.     /*
  446.      * If we haven't seen a -force_cpusubtype_ALL or an -arch flag for a
  447.      * specific architecture then let the machine instructions in the
  448.      * assembly determine the cpusubtype of the output file.
  449.      */
  450.     if(force_cpusubtype_ALL && specific_archflag)
  451.         archflag_cpusubtype = -1;
  452.  
  453.     /* Here with flags set up in flagseen[]. */
  454.     perform_an_assembly_pass(argc, argv); /* Assemble it. */
  455.  
  456.     if(seen_at_least_1_file() && bad_error != TRUE){
  457.         layout_addresses();
  458.         write_object(out_file_name);
  459.     }
  460.  
  461.     input_scrub_end();
  462.     md_end();            /* MACHINE.c */
  463.  
  464.     exit(bad_error);        /* WIN */
  465. }
  466.  
  467. /*            perform_an_assembly_pass()
  468.  *
  469.  * Here to attempt 1 pass over each input file.
  470.  * We scan argv[*] looking for filenames or exactly "" which is
  471.  * shorthand for stdin. Any argv that is NULL is not a file-name.
  472.  * We set need_pass_2 TRUE if, after this, we still have unresolved
  473.  * expressions of the form (unknown value)+-(unknown value).
  474.  *
  475.  * Note the un*x semantics: there is only 1 logical input file, but it
  476.  * may be a catenation of many 'physical' input files.
  477.  */
  478. static
  479. void
  480. perform_an_assembly_pass(
  481. int argc,
  482. char **argv)
  483. {
  484.     char *buffer;        /* Where each bufferful of lines will start. */
  485.     int saw_a_file;
  486.  
  487.     saw_a_file = 0;
  488.  
  489.     argv++;            /* skip argv[0] */
  490.     argc--;            /* skip argv[0] */
  491.     while(argc--){
  492.         if(*argv){        /* Is it a file-name argument? */
  493.         /* argv -> "" if stdin desired, else -> filename */
  494.         if((buffer = input_scrub_new_file(*argv))){
  495.             saw_a_file++;
  496.             read_a_source_file(buffer);
  497.         }
  498.         }
  499.         argv++;            /* completed that argv */
  500.     }
  501.     if(!saw_a_file)
  502.         if((buffer = input_scrub_new_file("")))
  503.             read_a_source_file(buffer);
  504. }
  505.  
  506. static
  507. void
  508. got_sig(
  509. int sig)
  510. {
  511.     static int here_before = 0;
  512.  
  513.     as_bad("Interrupted by signal %d",sig);
  514.     if(here_before++)
  515.         exit(1);
  516. }
  517.